{
	template:`
	<div style="padding:0 10px 10px;">
        <a-row :gutter="16" style="margin-bottom:10px;">
            <a-col :span="14">
                <a-dropdown>
                    <a-button type="link">添加根节点<m-icon name="icon-moreunfold" size="16"></m-icon></a-button>
                    <template #overlay>
                        <a-menu>
                            <a-menu-item v-for="item in eleRoot.default" @click="addNode(null,item,'default');">{{item}}</a-menu-item>
                        </a-menu>
                    </template>
                </a-dropdown>
                <a-tree :tree-data="eleTree" @select="treeSelect" @drop="treeDrop" :expandedKeys="expKeys" draggable >
                    <template #title="{ title, key }">
                        <span>{{ title }} {{eleMap[key].suffix}}</span><span v-if="key==selectEle.key">&nbsp;&gt;&gt;&gt;</span>
                    </template>
                </a-tree>
                <div style="text-align:right;margin:0 0 10px;">
                    <a-space>
                        <span style="color:#f30;">无保存功能，请及时复制保存成文件。</span>
                        <a-button type="primary" @click="toCode">生成代码</a-button>
                        预览宽度：
                        <a-input-number v-model:value="openWidth" />
                        <a-popover overlayClassName="index-popover" trigger="click" @openChange="toView">
                            <template #content><div id="pageTemp_view" :style="{width:openWidth+'px'}"></div></template>
                            <a-button type="default" :disabled="''==codeStr">预览</a-button>
                        </a-popover>
                    </a-space>
                </div>
                <a-textarea v-model:value="codeStr" :auto-size="{ minRows: 3, maxRows: 50 }" placeholder="编辑完成可点击生成代码查看"/>
            </a-col>
            <a-col v-if="selectEle&&selectEle.title" :span="10">
                <h4>编辑&nbsp;<span>{{selectEle.title}}</span></h4>
                <a-popconfirm title="确定要删除吗？" @confirm="delNode(selectEle.key,eleTree);selectEle={};">
                    <a-button type="link" danger>删除节点</a-button>
                </a-popconfirm>
                <a-dropdown v-if="eleTempSlot[selectEle.name]">
                    <a-button type="link">添加子节点<m-icon name="icon-moreunfold" size="16"></m-icon></a-button>
                    <template #overlay>
                        <a-menu>
                            <a-sub-menu v-for="(slot,key) in eleTempSlot[selectEle.name]" :key="key" :title="key">
                                <a-menu-item v-for="item in slot" @click="addNode(selectEle,item,key);">{{item}} {{item=='FormNormal'?'(推荐)':''}}</a-menu-item>
                            </a-sub-menu>
                        </a-menu>
                    </template>
                </a-dropdown>
                <a-button v-if="selectEle.name=='FormRow'||selectEle.name=='FormDesc'||selectEle.name=='FormNormal'" type="link" @click="addAllNode">批量添加</a-button>
                <a-form class="index-form" :wrapper-col="{span:24}">
                    <a-row :gutter="10">
                        <a-col v-for="(a,key) in selectEle.attr" :span="24">
                            <a-form-item class="index-form-item">
                                <template #label>{{a[0]}}</template>
                                <a-select v-if="a[3]&&options[a[3]]" v-model:value="selectEle.attr[key][1]" :options="options[a[3]]" @change="toSelectCode"></a-select>
                                <a-input v-else v-model:value="selectEle.attr[key][1]" :placeholder="'请输入'+a[0]" :addon-before="selectEle.attr[key][2]?(key+'=&quot;'):''" :addon-after="selectEle.attr[key][2]?'&quot;':''" @change="toSelectCode"></a-input>
                            </a-form-item>
                        </a-col>
                    </a-row>
                </a-form>
                <a-textarea v-model:value="selectCodeStr" :auto-size="{ minRows: 3, maxRows: 50 }"/>
            </a-col>
        </a-row>
    </div>
	`,
	props: ['localeZh','param','parentVue'],
	data:function(){
		return {
		    eleTemp:{
		        'PageHeader':'<a-page-header #{title} #{sub-title} #{extend}>\r\n\t<template #extra>#[extra]\r\n\t</template>#[default]\r\n</a-page-header>',
		        'Back':'<m-back @click="back(false);">#{text}</m-back>',
		        'Button':'<a-button #{type} #{@click}>#{text}</a-button>',
		        'FormRow':'<a-card :hoverable="true" :bodyStyle="{padding:\'20px 20px 0\'}">\r\n\t<a-form class="index-form" :wrapper-col="{span:24}">\r\n\t\t<a-row :gutter="10">#[items]\r\n\t\t</a-row>\r\n\t</a-form>\r\n</a-card>',
		        'FormRowItem':'<a-col #{:span}>\r\n\t<a-form-item #{label} class="index-form-item#{size}">\r\n\t\t#{type}\r\n\t</a-form-item>\r\n</a-col>',
		        'FormDesc':'<a-card :hoverable="true" :bodyStyle="{padding:0}">\r\n\t<a-descriptions #{column} bordered class="index-descriptions" style="margin:-1px;">#[items]\r\n\t</a-descriptions>\r\n</a-card>',
		        'FormDescItem':'<a-descriptions-item #{label}>\r\n\t#{type}\r\n</a-descriptions-item>',
		        'FormNormal':'<a-card :hoverable="true" :bodyStyle="{padding:0}">\r\n\t<a-descriptions #{column} class="index-normal">#[items]\r\n\t</a-descriptions>\r\n</a-card>',
		        'FormNormalItem':'<a-descriptions-item #{label}>\r\n\t#{type}\r\n</a-descriptions-item>',

		    },
		    eleTempAttr:{//[描述,默认值,是否属性] 不是属性的直接输出
		        'PageHeader':{'title':['标题','标题',true],'sub-title':['子标题','',true],'extend':['扩展属性','',false]},
		        'Back':{'text':['关闭文本','关闭',false]},
		        'Button':{'type':['类型','default',true,'buttonType'],'@click':['点击事件','',true],'text':['按钮文本','操作',false]},
		        'FormRowItem':{':span':['占位格数','12',true],'label':['标题','',true],'size':['标题尺寸','',false,'size'],'type':['组件类型','',false,'inputType'],
		            'v-model:value':['双向绑定','',true],'placeholder':['输入提示','',true],'dict':['字典属性','',false]},
		        'FormDesc':{'column':['列数','3',true]},
		        'FormDescItem':{'label':['标题','',true],'type':['组件类型','',false,'inputType'],
		            'v-model:value':['双向绑定','',true],'placeholder':['输入提示','',true],'dict':['字典属性','',false]},
		        'FormNormal':{'column':['列数','3',true]},
		        'FormNormalItem':{'label':['标题','',true],'type':['组件类型','',false,'inputType'],
		            'v-model:value':['双向绑定','',true],'placeholder':['输入提示','',true],'dict':['字典属性','',false]},
		    },
		    eleTempSlot:{
		        'PageHeader':{extra:['Back','Button'],default:['FormRow','FormDesc','FormNormal']},
		        'FormRow':{items:['FormRowItem']},
		        'FormDesc':{items:['FormDescItem']},
		        'FormNormal':{items:['FormNormalItem']},
		    },
		    eleTempTab:{
		        'PageHeader':{extra:2,default:1},
		        'FormRow':{items:3},
		        'FormRowItem':{input:2},
		        'FormDesc':{items:2},
		        'FormDescItem':{input:1},
		        'FormNormal':{items:2},
		        'FormNormalItem':{input:1},
		    },
		    eleRoot:{default:['PageHeader'],methods:[]},
		    eleTree:[],
		    eleMap:{},
		    expKeys:[],
		    idx:0,
		    selectEle:{},
		    selectCodeStr:'',
		    codeModel:{},
		    openWidth:800,
		    options:{
		        size:[{value:'',label:'默认'},{value:'-no',label:'无标题'},{value:'-sm',label:'小宽度'},{value:'-lg',label:'大宽度'}],
		        inputType:[{value:'',label:'无'},{value:'${input}',label:'文本框'},{value:'${textarea}',label:'文本域'},{value:'${number}',label:'数字框'},{value:'${date}',label:'日期框'},
		            {value:'${radio}',label:'单选按钮'},{value:'${checkbox}',label:'复选按钮'},{value:'${selectone}',label:'单选下拉框'},{value:'${selectmany}',label:'多选下拉框'}],
		        buttonType:[{value:'default',label:'默认'},{value:'primary',label:'主要 蓝色'},{value:'primary success',label:'成功 绿色'},{value:'primary warn',label:'警告 橙色'}]
		    },
		    codeStr:''
		};
	},
	mounted(){
	},
	methods:{
	    addNode:function(node,tag,slot){//添加到node下，节点名称，插槽
	        this.idx++;
	        let obj={slot:slot||'default',suffix:'',
	            title:"#"+(slot||'default')+" "+tag+" @"+this.idx,key:"k"+this.idx,children:[],
	            name:tag,temp:this.eleTemp[tag],
	            attr:{}
	        };
            if(this.eleTempAttr[tag]){
                for(let a in this.eleTempAttr[tag]){
                    let d=this.eleTempAttr[tag][a];
                    obj.attr[a]=[d[0],d[1],d[2],d[3]];
                }
            }
            this.eleMap[obj.key]=obj;
	        if(null!=node){
	            node.children.push(obj);
	            if(this.expKeys.indexOf(node.key)<0){
                    this.expKeys.push(node.key);
	            }
	            this.toSelectCode();
	        }else{
	            this.eleTree.push(obj);
	        }
	        this.eleTree=[...this.eleTree];
	        return obj;
	    },
	    addAllNode:function(){
	        if(this.selectEle.name=='FormRow'||this.selectEle.name=='FormDesc'||this.selectEle.name=='FormNormal'){
                this.parentVue.selectTableModel((model,fields)=>{
                    for(let i=0;i<fields.length;i++){
                        let f=fields[i];
                        let obj=this.addNode(this.selectEle,this.selectEle.name+'Item','items');
                        obj['attr']['label'][1]=f.field.description;
                        obj['attr']['v-model:value'][1]=f.key;
                        if(f.field.type=='STRING'){
                            if(f.field.dictOption){
                                obj['attr']['dict'][1]=f.field.clazz+'!'+f.field.field;
                                obj['attr']['type'][1]='${radio}';
                            }else if(f.field.dictType){
                                obj['attr']['dict'][1]=f.field.dictType;
                                obj['attr']['type'][1]='${selectone}';
                            }else{
                                obj['attr']['type'][1]='${input}';
                            }
                        }else if(f.field.type=='INT' || f.field.type=='DOUBLE'){
                            obj['attr']['type'][1]='${number}';
                        }else if(f.field.type=='DATE'){
                            obj['attr']['type'][1]='${date}';
                        }
                    }
                });
	        }
	    },
	    delNode:function(key,list){
	        for(let i=0;i<list.length;i++){
	            let ele=list[i];
	            if(ele.key==key){
	                return list.splice(i, 1)[0];
	            }else{
	                let r=this.delNode(key,ele.children);
	                if(null!=r) return r;
	            }
	        }
	        return null;
	    },
	    appendNode:function(node,nextKey,list){
	        for(let i=0;i<list.length;i++){
	            let ele=list[i];
	            if(ele.key==nextKey){
	                list.splice(i+1, 0, node);;
	                return true;
	            }else{
	                if(this.appendNode(node,nextKey,ele.children)){
	                    return true;
	                }
	            }
	        }
	        return false;
	    },
	    unshiftNode:function(node,parentKey,list){
	        for(let i=0;i<list.length;i++){
	            let ele=list[i];
	            if(ele.key==parentKey){
	                ele.children.unshift(node);;
	                return true;
	            }else{
	                if(this.unshiftNode(node,parentKey,ele.children)){
	                    return true;
	                }
	            }
	        }
	        return false;
	    },
	    treeDrop:function(e){
	        let n1=e.dragNode,n2=e.node;
	        let pos1=n1.pos,pos2=n2.pos;
	        if(pos1.substring(0,pos1.lastIndexOf("-"))==pos2.substring(0,pos2.lastIndexOf("-"))){
                let node=this.delNode(n1.key,this.eleTree);
                if(null==n1.parent&&e.dropPosition==-1){
                    this.eleTree.unshift(node);
                }else{
                    this.appendNode(node,n2.key,this.eleTree);
                }
	        }else if(!e.dropToGap&&null!=n1.parent&&n1.parent.key==n2.key){
                let node=this.delNode(n1.key,this.eleTree);
                this.unshiftNode(node,n2.key,this.eleTree);
	        }else{
	            this.remind().error("只能拖拽到同级");
	        }
	    },
	    treeSelect:function(keys,e){
	        if(e.selectedNodes.length>0){
	            this.selectEle=e.selectedNodes[0];
	            this.toSelectCode();
	        }else{
	            this.selectEle={};
	        }
	    },
	    toSelectCode:function(){
	        if(this.selectEle&&this.selectEle.title){
                let code="\r\n\t"+this.toEleCode(this.selectEle,1);
                code=code.replace(/\r\n\t/g,"\r\n");
                this.selectCodeStr=code.length>1?code.substring(2):code;
	        }
	    },
	    //转换成代码
	    toCode:function(){
	        this.codeModel={};
            let code="{\r\n\ttemplate:`";
            for(let i=0;i<this.eleTree.length;i++){
                code+="\r\n\t";
                code+=this.toEleCode(this.eleTree[i],1);
            }
            code+="\r\n\t`,\r\n\tprops: ['localeZh','param','parentVue'],";
            code+="\r\n\tdata:function(){\r\n\t\treturn {\r\n\t\t\tmodel:"+JSON.stringify(this.codeModel)+"\r\n\t\t};\r\n\t},";
            code+="\r\n\tmounted(){\r\n\t},";
            code+="\r\n\tmethods:{\r\n\t}";
            code+="\r\n}";
            this.codeStr=code;
	    },
	    addModelAttr:function(model,p){
	        if(p.indexOf(".")>0){
	            let attr=p.substring(0,p.indexOf('.'));
	            if(!model[attr]){
	                model[attr]={};
	            }
	        }
	    },
	    //元素转换成代码
	    toEleCode:function(ele,nt){
            if(ele.name=='FormRowItem'||ele.name=='FormDescItem'||ele.name=='FormNormalItem') ele.suffix=ele.attr['label'][1];
            let code=ele.temp;
            let arr=code.match(/#{.*?}/g);
            if(null!=arr){
                for(let i=0;i<arr.length;i++){
                    let a=arr[i].substring(2,arr[i].length-1);
                    let d=ele.attr[a];
                    if(a=='v-model:value'&&d[1].indexOf("model.")>=0){
                        this.addModelAttr(this.codeModel,d[1].substring(6));
                    }
                    if(d&&d[1]){
                        code=code.replace(arr[i],d[2]?(a+'="'+d[1]+'"'):d[1]);
                    }else{
                        code=code.replace(arr[i],'');
                    }
                }
            }
            arr=code.match(/#\[.*?\]/g);
            if(null!=arr){
                for(let i=0;i<arr.length;i++){
                    let a=arr[i].substring(2,arr[i].length-1);
                    code=code.replace(arr[i],this.toSlotEleCode(ele,a,this.eleTempTab[ele.name][a]));
                }
            }
            code=this.toConvert(ele,code);
            return code.replace(/\r\n/g,"\r\n"+this.toNT(nt));
	    },
	    toSlotEleCode(ele,slot,nt){
            let code="";
            for(let i=0;i<ele.children.length;i++){
                if(ele.children[i].slot==slot){
                    code+="\r\n"+this.toNT(nt);
                    code+=this.toEleCode(ele.children[i],nt);
                }
            }
            return code;
	    },
	    toNT:function(n){
	        let s="";
	        for(let i=0;i<n;i++) s+="\t";
	        return s;
	    },
	    toConvert:function(ele,code){
	        let arr=code.match(/\${.*?}/g);
            if(null!=arr){
                for(let i=0;i<arr.length;i++){
                    let a=arr[i].substring(2,arr[i].length-1);
                    let el={attr:ele.attr};
                    if(a=='input') el.temp='<a-input #{v-model:value} #{placeholder}/>';
                    else if(a=='textarea') el.temp='<a-textarea #{v-model:value} #{placeholder} auto-size/>';
                    else if(a=='number') el.temp='<a-input-number #{v-model:value} #{placeholder}/>';
                    else if(a=='date') el.temp='<a-date-picker #{v-model:value} #{placeholder} format="YYYY-MM-DD" valueFormat="YYYY-MM-DD" style="width:100%;" />';
                    else if(a=='radio') el.temp='<a-radio-group #{v-model:value} :options="dictOptions(\'#{dict}\')" />';
                    else if(a=='checkbox') el.temp='<a-checkbox-group #{v-model:value} :options="dictOptions(\'#{dict}\')" />';
                    else if(a=='selectone') el.temp='<a-select #{v-model:value} #{placeholder} :options="dictOptions(\'#{dict}\')" show-search :filter-option="selectFilter"/>';
                    else if(a=='selectmany') el.temp='<a-select #{v-model:value} #{placeholder} :options="dictOptions(\'#{dict}\')" mode="multiple" show-arrow show-search :filter-option="selectFilter"/>';
                    else el.temp='';
                    code=code.replace(arr[i],this.toEleCode(el,0));
                }
            }
	        return code;
	    },
	    toView:function(flag){
	        if(flag){
                if(this.codeStr){
                    setTimeout(()=>{
                        this.loadTemp("pageTemp_view",this.codeStr);
                    },30);
                }else{
                    this.remind().error("请先生成代码");
                }
	        }
	    }
	}
}